package com.feri.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.feri.api.config.RedisKeyConfig;
import com.feri.api.config.SystemConfig;
import com.feri.api.dao.ScorelogDao;
import com.feri.api.dao.UserDao;

import com.feri.api.dao.UserlevelDao;
import com.feri.api.dao.UserlogDao;
import com.feri.api.dto.UserAddDto;
import com.feri.api.dto.UserLoginCodeDto;
import com.feri.api.dto.UserLoginDto;
import com.feri.api.service.intf.UserService;
import com.feri.api.service.intf.UserlevelService;
import com.feri.api.util.JedisUtil;
import com.feri.api.util.PassUtils;
import com.feri.api.vo.R;
import com.feri.common.entity.User;
import com.feri.common.entity.Userlog;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.sql.SQLException;

/**
 * ━━━━━━神兽出没━━━━━━
 * 　　　┏┓　　　┏┓
 * 　　┏┛┻━━━┛┻┓
 * 　　┃　　　　　　 ┃
 * 　　┃　　　━　　　┃
 * 　　┃　┳┛　┗┳　  ┃
 * 　　┃　　　　　　 ┃
 * 　　┃　　　┻　　　┃
 * 　　┃　　　　　　　┃
 * 　　┗━┓　　　┏━┛Code is far away from bug with the animal protecting
 * 　　　　┃　　　┃    神兽保佑,代码无bug
 * 　　　　┃　　　┃
 * 　　　　┃　　　┗━━━┓
 * 　　　　┃　　　　　　　┣┓
 * 　　　　┃　　　　　　　┏┛
 * 　　　　┗┓┓┏━┳┓┏┛
 * 　　　　　┃┫┫　┃┫┫
 * 　　　　　┗┻┛　┗┻┛
 * ━━━━━━永无BUG!━━━━━━
 *
 * @Description:
 * @Author: 学习强国
 * @Date: 2022/10/02 13:26:55
 */
@Service
public class UserServiceImpl implements UserService {
    private final UserDao dao;
    private final UserlogDao logDao;
    private final ScorelogDao scorelogDao;
    private final UserlevelDao levelDao;
    private final UserlevelService levelService;
    public UserServiceImpl(UserDao dao, UserlogDao logDao, ScorelogDao scorelogDao, UserlevelDao levelDao,UserlevelService levelService) {
        this.dao = dao;
        this.logDao = logDao;
        this.scorelogDao = scorelogDao;
        this.levelDao = levelDao;
        this.levelService = levelService;
    }
    /**
     * 实现用户注册
     * 开启事务
     */
    @Override
    @Transactional(rollbackFor = SQLException.class)
    public R register(UserAddDto dto, String token) {
        //1.入参校验
        if (dto != null) {
            //2.校验内容是不是空
            if (StringUtils.hasLength(dto.getPhone()) && StringUtils.hasLength(dto.getPassword())) {
                //防止直接请求接口
                //3.查询用户
                User user = getUser(dto.getPhone());
                //4.验证手机号是否存在
                if (user == null) {
                    //4.验证账号是否有效
                    //如何保证验证码测试通过，才可以注册用户？
                    //5.校验是否通过了手机验证码的校验，通过看才可以注册
                    if (JedisUtil.existsSet(RedisKeyConfig.USER_ADDPHONES, dto.getPhone())) {
                        //6.设置要注册的用户
                        user = new User(dto.getPhone(), PassUtils.aesenc(SystemConfig.PASS_KEY, dto.getPassword()));
                        //7.验证操作数据库是否成功
                        if (dao.insert(user) > 0) {
                            //8.新增成功,删除之前记录的手机号
                            JedisUtil.delSet(RedisKeyConfig.USER_ADDPHONES, dto.getPhone());
                            //新人有礼
                            //9.初始化会员等级
//                            levelDao.insert(new Userlevel(user.getId(), 50L, "第一次注册，奖励积分，完成等级初始化"));
//                            scorelogDao.insert(new Scorelog(user.getId(), 1, 50, "新人奖励50积分"));
                            //10 记录日志
                            logDao.insert(new Userlog(user.getId(), 1, "用户完成注册"));

                            return R.ok(null);
                        }else {
                            return R.fail("sql异常");
                        }
                    }else {
                        return R.fail("请输入验证码");
                    }
                }else {
                    return R.fail("手机号已经存在了亲！");
                }

            }else {
                return R.fail();
            }
        }else { return R.fail();
        }

    }

    @Override
    public R checkPhone(String phone) {
        //1.入参校验
        if (StringUtils.hasLength(phone)) {
            //2.正则校验
            if (phone.matches(SystemConfig.PHONE_RX)) {
                //3.查询数据库
                User user = getUser(phone);
                //4.验证数据库里是否存在
                if (user == null) {
                    //可用
                    return R.ok(null);
                }
            }
        }
        return R.fail();
    }

//    @Override
//    public R querymy(String token) {
//        //1.校验
//        if (StringUtils.hasLength(token)) {
//            //2.查询返回
//            return R.ok(dao.selectMyById(Long.parseLong(token)));
//        }
//        return R.fail();
//    }

    @Override
    public R all() {
        return R.ok(dao.selectList(null));
    }

    /**
     * 唯一登录：一个账号，只能在线1个
     */
    @Override
    public R loginPassword(UserLoginDto dto, String token) {
        //手机号密码登录
        //1.校验
        if (dto != null) {
            if (StringUtils.hasLength(dto.getPhone())) {
                //2.查询数据库
                User user = getUser(dto.getPhone());
                //3.验证是否存在用户
                if (user != null) {
                    //4.验证账号是否有效
                    if (user.getFlag() == SystemConfig.USER_OK) {
                        //5.验证密码
                        if (user.getPassword().equals(PassUtils.aesenc(SystemConfig.PASS_KEY, dto.getPassword()))) {
                            //6.账号 密码正确 生成令牌 存储并返回
                            return createToken(dto.getPhone(), user.getId(), "账号密码",token);
                        }
                    }
                }
            }
        }
        return R.fail("亲，账号或密码不正确！");
    }
    /**
     *选择：手机号验证码登录 */
    @Override
    public R loginCode(UserLoginCodeDto dto, String token) {
        //手机号验证码登录
        //1.校验
        if (dto != null) {
            User user = getUser(dto.getPhone());
            //3.验证是否存在用户
            if (user != null) {

                //4.验证账号是否有效
                if (user.getFlag() == SystemConfig.USER_OK) {
                    if (JedisUtil.exists(RedisKeyConfig.USER_LOGINCODE + dto.getPhone())) {

                        //5.验证 对应的验证码
                        if (JedisUtil.getString(RedisKeyConfig.USER_LOGINCODE + dto.getPhone()).equals(dto.getCode())) {
                            //删除验证码
                            JedisUtil.delKey(RedisKeyConfig.USER_LOGINCODE + dto.getPhone());
                            //6.账号 密码正确 生成令牌 存储并返回
                            return createToken(dto.getPhone(), user.getId(), "手机号验证码",token);
                        }
                    }
                }
            }
        }
        return R.fail("亲，手机号或验证码不正确！");
    }

    @Override
    public R loginOut(String phone) {
        //1.校验参数
        if(StringUtils.hasLength(phone)) {
            //2.校验当前手机号 是否在线
            if(JedisUtil.exists(RedisKeyConfig.USER_PHONE + phone)){
                //3.退出登录
                JedisUtil.delKey(RedisKeyConfig.USER_PHONE + phone);
                return R.ok();
            }else {
                return R.fail("亲，登录已失效");
            }
        }else {
            return R.fail("亲，你还没有登录呢");
        }

    }

    @Override
    public R queryAll() {
        return null;
    }

    @Override
    public R checkToken(String phone) {
        //1.校验参数
        if (StringUtils.hasLength(phone)) {
            //2.验证是存在挤掉信息
            if (JedisUtil.existsHash(RedisKeyConfig.USER_LOGIN_DROP, phone)) {
                //你被挤掉了
                JedisUtil.delHash(RedisKeyConfig.USER_LOGIN_DROP, phone);
                return R.ok("亲，你被挤掉了！");
            }
        }
        return R.fail();
    }

//    @Override
//    public R updateuser(UpdateUserDto dto, String token) {
//        User user = dao.selectOne(new QueryWrapper<User>().eq("id", Long.parseLong(token)));
//        user.setNickname(dto.getNickname());
//        user.setImgurl(dto.getImgurl());
//        if (dao.updateById(user)>0){
//            return R.ok();
//        }
//        return R.fail();
//    }

    /**
     * 1.查询用户
     */
    private User getUser(String phone){
        //1.校验
        if (StringUtils.hasLength(phone)) {
            //2.查询数据库
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("phone",phone);
            return dao.selectOne(wrapper);
        }
        return null;
    }

    /**2.实现登录的令牌存储*/
    private R createToken(String phone, long uid, String msg,String ip) {
        //1.验证当前账号是否已经在线
        if (JedisUtil.exists(RedisKeyConfig.USER_PHONE + phone)) {
            //2.如果存在，唯一登录，挤掉信息 存储 Redis
            JedisUtil.addHash(RedisKeyConfig.USER_LOGIN_DROP, phone, "亲。你在其他设备已登录！");
            //调用极光推送的Api 实现消息推送  省略
        }
        //3.生成令牌  简单的形式，直接使用 用户id
        String token = uid + "";
        //4.存储令牌 到Redis中
        //Redis:1.为什么使用  2.有没有有效期 3.什么数据类型 4.存储什么数据
        JedisUtil.addString(RedisKeyConfig.USER_PHONE + phone, token, RedisKeyConfig.USER_PHONE_TIME);
        //5.验证是否每日首次登录
        if(logDao.selectLoginlog(uid)== null){
            //每日首次登录 奖励积分
            //6.更新积分并校验等级是否需要升级
//            levelService.updateLevel(uid,10);
            //7.记录积分变动流水
//            scorelogDao.insert(new Scorelog(uid,1,10,"每日首次登录，奖励10积分"));
        }
        //8.记录用户登录日志
        logDao.insert(new Userlog(uid, 2, "用户通过" + msg + "登录成功"));

        return R.ok(token);
    }
}